/**
 * UDP 通信管理类
 * 负责处理 UDP Socket 的创建、数据收发、心跳维护等功能
 */
import CommandManager from './commandManager';
import ElectricalDataCommand from './commands/electricalDataCommand';

class UDPManager {
  constructor() {
    // Socket 实例
    this.socket = null;
    // Socket 状态
    this.isConnected = false;
    // 心跳定时器
    this.heartbeatTimer = null;
    // 目标设备信息
    this.targetInfo = null;
    // 事件回调
    this.onMessageCallback = null;
    this.onErrorCallback = null;
    // 调试模式
    this.debug = true;
    // 查询定时器
    this.queryTimer = null;
    // 查询间隔（毫秒）
    this.queryInterval = 1000; // 每秒查询一次
    this.messageHandlers = new Set(); // 添加消息处理器集合
    this.expectedCommand = null; // 添加期望的命令类型
    this.responseHandler = null; // 添加响应处理器
  }

  /**
   * 创建 UDP Socket 并开始监听
   * @param {string} ip - 目标设备IP
   * @param {number} port - 目标设备端口
   * @returns {Promise} 连接结果
   */
  connect(ip, port) {
    this.log('准备创建 Socket:', { ip, port });

    if (this.isConnected) {
      this.warn('Socket 已创建');
      return Promise.reject(new Error('Socket 已创建'));
    }

    return new Promise((resolve, reject) => {
      try {
        // 创建 UDP Socket
        this.socket = wx.createUDPSocket();
        this.targetInfo = { 
          address: ip, 
          port: parseInt(port) 
        };

        // 绑定随机端口
        const bindPort = this.socket.bind();
        this.log('绑定本地端口:', bindPort);

        // 监听消息
        this.socket.onMessage(this.handleMessage.bind(this));

        // 设置连接状态
        this.isConnected = true;
        this.log('Socket 创建成功');
        resolve();

      } catch (error) {
        this.error('创建 Socket 失败:', error);
        this.handleError(error);
        reject(error);
      }
    });
  }

  /**
   * 发送数据
   * @param {string|Uint8Array|ArrayBuffer} data - 要发送的数据
   * @returns {Promise} 发送结果
   */
  send(data) {
    if (!this.isConnected || !this.socket || !this.targetInfo) {
      this.error('发送失败: Socket未创建或目标地址未设置');
      return Promise.reject(new Error('Socket未创建或目标地址未设置'));
    }

    return new Promise((resolve, reject) => {
      try {
        const buffer = this.convertToBuffer(data);
        if (!buffer) {
          throw new Error('数据转换失败');
        }

        this.socket.send({
          address: this.targetInfo.address,
          port: this.targetInfo.port,
          message: buffer,
          success: () => {
            this.log('数据发送成功');
            resolve();
          },
          fail: (err) => {
            this.error('发送数据失败:', err);
            reject(err);
          }
        });
      } catch (error) {
        this.error('发送数据时出错:', error);
        reject(error);
      }
    });
  }

  /**
   * 启动心跳包
   * @param {number} interval - 心跳间隔(ms)
   */
  startHeartbeat(interval = 5000) {
    this.stopHeartbeat();
    this.log('启动心跳包, 间隔:', interval);

    this.heartbeatTimer = setInterval(() => {
      if (!this.isConnected) {
        this.log('未连接，停止心跳');
        this.stopHeartbeat();
        return;
      }

      const heartbeat = new Uint8Array([0xFF]);
      this.log('发送心跳包');
      
      this.send(heartbeat).catch(err => {
        this.error('心跳包发送失败:', err);
        this.handleError(err);
      });
    }, interval);
  }

  /**
   * 停止心跳包
   */
  stopHeartbeat() {
    if (this.heartbeatTimer) {
      clearInterval(this.heartbeatTimer);
      this.heartbeatTimer = null;
      this.log('心跳包已停止');
    }
  }

  /**
   * 启动电气参数查询
   */
  startQuery() {
    this.stopQuery();
    this.log('启动电气参数查询, 间隔:', this.queryInterval);

    // 立即执行一次查询
    this.queryElectricalData();

    // 设置定时查询
    this.queryTimer = setInterval(() => {
      this.queryElectricalData();
    }, this.queryInterval);
  }

  /**
   * 停止查询
   */
  stopQuery() {
    if (this.queryTimer) {
      clearInterval(this.queryTimer);
      this.queryTimer = null;
      this.log('电气参数查询已停止');
    }
  }

  /**
   * 查询电气参数
   */
  queryElectricalData() {
    if (!this.isConnected) {
      this.log('未连接，取消查询');
      return;
    }

    try {
      // 打包查询命令
      const frame = CommandManager.createCommand('ELECTRICAL_DATA');
      if (!frame) {
        this.error('创建查询命令失败');
        return;
      }

      this.log('发送查询命令:', Array.from(frame).map(b => `0x${b.toString(16).padStart(2, '0')}`).join(' '));

      // 发送查询命令
      this.send(frame).catch(err => {
        this.error('查询命令发送失败:', err);
      });
    } catch (err) {
      this.error('查询电气参数错误:', err);
    }
  }

  /**
   * 设置消息回调
   */
  onMessage(callback) {
    if (callback) {
      this.messageHandlers.add(callback);
    }
  }

  /**
   * 移除消息回调
   */
  offMessage(callback) {
    if (callback) {
      this.messageHandlers.delete(callback);
    }
  }

  /**
   * 处理接收到的消息
   * @private
   */
  handleMessage(res) {
    try {
      const { message, remoteInfo } = res;
      const data = new Uint8Array(message);
      
      this.log('收到数据:', {
        data: Array.from(data).map(b => `0x${b.toString(16).padStart(2, '0')}`).join(' '),
        remoteInfo
      });

      // 通知所有消息处理器
      this.messageHandlers.forEach(handler => {
        try {
          handler(data);
        } catch (err) {
          this.error('消息处理器执行错误:', err);
        }
      });
    } catch (err) {
      this.error('处理接收数据错误:', err);
    }
  }

  /**
   * 处理错误
   * @private
   */
  handleError(error) {
    this.error('错误:', error);
    this.onErrorCallback && this.onErrorCallback(error);
  }

  /**
   * 转换数据为 ArrayBuffer
   * @private
   */
  convertToBuffer(data) {
    let buffer;
    if (typeof data === 'string') {
      const bytes = new Uint8Array(data.length);
      for (let i = 0; i < data.length; i++) {
        bytes[i] = data.charCodeAt(i);
      }
      buffer = bytes.buffer;
      this.log('字符串转换为字节:', Array.from(bytes).map(b => `0x${b.toString(16).padStart(2, '0')}`).join(' '));
    } else if (data instanceof Uint8Array) {
      buffer = data.buffer;
      this.log('Uint8Array 数据:', Array.from(data).map(b => `0x${b.toString(16).padStart(2, '0')}`).join(' '));
    } else if (data instanceof ArrayBuffer) {
      buffer = data;
      this.log('ArrayBuffer 数据:', Array.from(new Uint8Array(data)).map(b => `0x${b.toString(16).padStart(2, '0')}`).join(' '));
    } else {
      this.error('不支持的数据类型:', typeof data);
      return null;
    }
    return buffer;
  }

  /**
   * 日志方法
   * @private
   */
  log(...args) {
    if (this.debug) console.log('[UDP]', ...args);
  }

  warn(...args) {
    if (this.debug) console.warn('[UDP]', ...args);
  }

  error(...args) {
    if (this.debug) console.error('[UDP]', ...args);
  }

  /**
   * 设置错误回调
   */
  onError(callback) {
    this.onErrorCallback = callback;
  }

  /**
   * 关闭连接
   */
  disconnect() {
    this.stopQuery(); // 停止查询
    this.log('准备关闭连接');
    this.stopHeartbeat();

    if (this.socket) {
      this.socket.close();
      this.socket = null;
      this.log('Socket 已关闭');
    }

    this.isConnected = false;
    this.targetInfo = null;
    return Promise.resolve();
  }

  /**
   * 发送命令并等待响应
   * @param {Uint8Array} frame - 要发送的命令帧
   * @param {number} timeout - 超时时间(ms)
   * @returns {Promise<Uint8Array>} 响应数据
   */
  sendAndWait(frame, timeout = 3000) {
    return new Promise((resolve, reject) => {
      // 设置超时
      const timeoutTimer = setTimeout(() => {
        this.removeResponseHandler();
        reject(new Error('等待响应超时'));
      }, timeout);

      // 设置响应处理器
      const responseHandler = (response) => {
        try {
          // 检查是否是期望的命令响应
          const cmd = response[4]; // 命令字节
          if (cmd === this.expectedCommand) {
            clearTimeout(timeoutTimer);
            this.removeResponseHandler();
            resolve(response);
          }
        } catch (err) {
          this.error('处理响应数据错误:', err);
        }
      };

      // 保存响应处理器和期望的命令
      this.responseHandler = responseHandler;
      this.expectedCommand = frame[4]; // 保存期望的命令类型
      this.onMessage(responseHandler);

      // 发送命令
      this.send(frame).catch(err => {
        clearTimeout(timeoutTimer);
        this.removeResponseHandler();
        reject(err);
      });
    });
  }

  /**
   * 移除响应处理器
   * @private
   */
  removeResponseHandler() {
    if (this.responseHandler) {
      this.offMessage(this.responseHandler);
      this.responseHandler = null;
      this.expectedCommand = null;
    }
  }

  // 添加清除所有消息处理器的方法
  clearMessageHandlers() {
    this.messageHandlers.clear();
  }
}

export default UDPManager;